package com.gaofans.nrpc.server.bootstrap;

import com.gaofans.nrpc.common.compress.Codec;
import com.gaofans.nrpc.common.compress.CodecFactory;
import com.gaofans.nrpc.common.compress.Identity;
import com.gaofans.nrpc.common.id.IdGenerator;
import com.gaofans.nrpc.common.processor.Builder;
import com.gaofans.nrpc.common.serializer.SerializerFactory;
import com.gaofans.nrpc.server.service.ServiceBinder;
import io.netty.channel.ChannelOption;
import io.netty.handler.ssl.SslContext;

import java.util.Objects;

/**
 * server创建者
 * @author GaoFans
 */
public class RpcServerBuilder implements Builder<RpcServer> {

    private final ServerBootstrapConfig config;

    public RpcServerBuilder() {
        this.config = new ServerBootstrapConfig();
    }

    public RpcServerBuilder port(int port){
        config.setPort(port);
        return this;
    }

    public RpcServerBuilder parentThreadCount(int count){
        config.setParentThreadCount(count);
        return this;
    }

    public RpcServerBuilder childThreadCount(int count){
        config.setChildThreadCount(count);
        return this;
    }

    public RpcServerBuilder workerThreadCount(int count){
        config.setWorkerThreadCount(count);
        return this;
    }

    public RpcServerBuilder handlerThreadCount(int count){
        config.setHandlerThreadCount(count);
        return this;
    }

    @SuppressWarnings("rawtypes")
    public RpcServerBuilder setOption(ChannelOption key, Object value){
        config.setOptionMap(Objects.requireNonNull(key),value);
        return this;
    }

    public RpcServerBuilder serializerFactory(SerializerFactory factory){
        config.setSerializerFactory(Objects.requireNonNull(factory));
        return this;
    }

    public RpcServerBuilder serializerType(byte type){
        config.setSerializerType(type);
        return this;
    }

    public RpcServerBuilder version(short version){
        config.setVersion(version);
        return this;
    }

    public RpcServerBuilder idGenerator(IdGenerator idGenerator){
        config.setIdGenerator(Objects.requireNonNull(idGenerator));
        return this;
    }

    public RpcServerBuilder codec(Codec codec){
        config.setCodec(Objects.requireNonNull(codec));
        //注册codec
        if (CodecFactory.get(codec.getMessageEncoding()) == null){
            CodecFactory.register(codec.getMessageEncoding(),codec);
        }
        return this;
    }

    public RpcServerBuilder readerIdleTimeSecond(int second){
        config.setReaderIdleTimeSecond(second);
        return this;
    }

    public RpcServerBuilder writerIdleTimeSecond(int second){
        config.setWriterIdleTimeSecond(second);
        return this;
    }

    public RpcServerBuilder sslContext(SslContext sslContext){
        config.setSslContext(Objects.requireNonNull(sslContext));
        return this;
    }


    @Override
    public RpcServer build() {
        if (config.getCodec() == null){
            config.setCodec(new Identity());
        }
        if (config.getSerializerFactory() == null){
            config.setSerializerFactory(new SerializerFactory());
        }
        if (config.getSerializerFactory().getSerializer(config.getSerializerType()) == null){
            throw new IllegalStateException("找不到指定类型的序列化器");
        }
        if (config.getIdGenerator() == null){
            config.setIdGenerator(IdGenerator.getInstance());
        }
        if (config.getPort() <= 1024 && config.getPort() > 65535){
            throw new IllegalStateException("端口不正确");
        }
        return new NettyRpcServer(config,new ServiceBinder());
    }
}
